package cn.kgc.springboot.vue.service.impl;

import cn.hutool.core.util.RandomUtil;
import cn.hutool.json.JSONUtil;
import cn.kgc.springboot.vue.commons.QueryCondition;
import cn.kgc.springboot.vue.entity.Permission;
import cn.kgc.springboot.vue.entity.RolePermission;
import cn.kgc.springboot.vue.entity.User;
import cn.kgc.springboot.vue.entity.UserRole;
import cn.kgc.springboot.vue.exception.BusinessException;
import cn.kgc.springboot.vue.form.UserForm;
import cn.kgc.springboot.vue.mapper.*;
import cn.kgc.springboot.vue.response.ResponseResult;
import cn.kgc.springboot.vue.service.UserService;
import cn.kgc.springboot.vue.utils.IpUtil;
import cn.kgc.springboot.vue.utils.JWTUtil;
import cn.kgc.springboot.vue.vo.UserVO;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import org.apache.shiro.crypto.hash.SimpleHash;
import org.springframework.beans.BeanUtils;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * @author mengshun
 * @description 针对表【sys_user】的数据库操作Service实现
 * @createDate 2024-12-18 09:40:46
 */
@Service
@Transactional
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {

    @Resource
    private StringRedisTemplate stringRedisTemplate;
    @Resource
    private JWTUtil jwtUtil;

    @Resource
    private DeptMapper deptMapper;

    @Resource
    private UserRoleMapper userRoleMapper;

    @Resource
    private RoleMapper roleMapper;


    @Resource
    private RolePermissionMapper rolePermissionMapper;

    @Resource
    private PermissionMapper permissionMapper;

    @Override
    public ResponseResult login(HashMap<String, String> params, HttpServletRequest request) {

        // 比较验证码
        String formCode = params.get("code");
        String uuid = params.get("uuid");
        String redisCode = stringRedisTemplate.opsForValue().get(uuid);

        if (ObjectUtils.isNull(redisCode)) {
            return ResponseResult.fail().message("验证码失效,请重新获取");
        }

        if (Double.parseDouble(formCode) != Double.parseDouble(redisCode)) {
            return ResponseResult.fail().message("验证码错误");
        }

        // 比较用户名和密码  shiro   Subject  login   jwt
        String username = params.get("username");
        LambdaQueryWrapper<User> userLambdaQueryWrapper = new LambdaQueryWrapper<>();
        userLambdaQueryWrapper.eq(User::getUsername, username);
        User user = baseMapper.selectOne(userLambdaQueryWrapper);
        if (ObjectUtils.isNull(user)) {
            return ResponseResult.fail().message("用户名不正确");
        }

        Integer state = user.getState();
        if (state==0){
            throw  new BusinessException("当前用户被禁用,请联系管理员");
        }


        String formPassword = params.get("password");
        String DBPassword = user.getPassword();
        String salt = user.getSalt();

        // 加密前端的
        String hashFormPassword = new SimpleHash("MD5", formPassword, salt, 10).toHex();

        if (!DBPassword.equals(hashFormPassword)) {
            return ResponseResult.fail().message("密码不正确");
        }


        // TODO 认证通过   颁发token
        HashMap<String, Object> tokenMap = new HashMap<>();
        tokenMap.put("username", user.getUsername());
        tokenMap.put("id", user.getId());
        String token = jwtUtil.createToken("userInfo", tokenMap);


        // 存储token   便于后续的状态判定
        String ip = IpUtil.getIp(request);
        stringRedisTemplate.opsForValue().set(token, ip);

        return ResponseResult.success()
                .message("认证通过")
                .data("token", token)
                .data("nickName", user.getNickName());
    }

    @Override
    public ResponseResult getPersonalInfo(String token) {
        Map<String, Object> tokenMap = jwtUtil.analyzingToken("userInfo", token);
        Integer id = (Integer) tokenMap.get("id");

        User user = baseMapper.selectById(id);
        return ResponseResult.success().data("personal", user);
    }

    @Override
    public ResponseResult editPersonalPwd(String token, HashMap<String, Object> params) {
        Map<String, Object> tokenMap = jwtUtil.analyzingToken("userInfo", token);
        Integer id = (Integer) tokenMap.get("id");
        User user = baseMapper.selectById(id);
        String DBPassword = user.getPassword();
        String oldPassword = (String) params.get("oldPassword");
        String hashOldPassword = new SimpleHash("MD5", oldPassword, user.getSalt(), 10).toHex();

        if (!DBPassword.equals(hashOldPassword)) {
            return ResponseResult.fail().message("原始密码不正确");
        }

        String randomSalt = RandomUtil.randomString(8);
        String newPassword = (String) params.get("newPassword");
        String hashNewPassword = new SimpleHash("MD5", newPassword, randomSalt, 10).toHex();

        User usr = new User();
        usr.setId(user.getId());
        usr.setSalt(randomSalt);
        usr.setPassword(hashNewPassword);

        baseMapper.updateById(usr);

        return ResponseResult.success().message("密码修改成功");
    }

    @Override
    public ResponseResult logout(String token) {

        stringRedisTemplate.delete(token);
        return ResponseResult.success();
    }

    @Override
    public ResponseResult editPersonalInfo(HashMap<String, Object> params) {

        String code = (String) params.get("code");
        String email = (String) params.get("email");

        String redisCode = stringRedisTemplate.opsForValue().get(email);
        if (StringUtils.isEmpty(redisCode)) {
            return ResponseResult.fail().message("验证码失效");
        }

        if (!redisCode.equals(code)) {
            return ResponseResult.fail().message("验证码错误");
        }

        User user = new User();
        String nickName = (String) params.get("nickName");
        Integer sex = (Integer) params.get("sex");
        String addr = (String) params.get("city");
        String tel = (String) params.get("tel");
        Integer id = (Integer) params.get("id");


        user.setNickName(nickName);
        user.setSex(sex);
        user.setCity(addr);
        user.setTel(tel);
        user.setEmail(email);
        user.setId(id);

        baseMapper.updateById(user);

        return ResponseResult.success();
    }

    @Override
    public ResponseResult userPage(QueryCondition<User> queryCondition) {

        Integer page = queryCondition.getPage();
        Integer limit = queryCondition.getLimit();

        // 获取搜索条件
        User searchParams = queryCondition.getSearchParams();
        String username = searchParams.getUsername();
        Integer deptId = searchParams.getDeptId();
        Integer state = searchParams.getState();

        // 创建动态条件构造器
        LambdaQueryWrapper<User> lambda = new QueryWrapper<User>().lambda();
        lambda.like(StringUtils.isNotBlank(username), User::getUsername, username)
                .eq(ObjectUtils.isNotNull(deptId), User::getDeptId, deptId)
                .eq(ObjectUtils.isNotNull(state), User::getState, state)
                .orderByDesc(User::getCreateTime);

        // 创建分页对象
        Page<User> userPage = new Page<>(page, limit);
        baseMapper.selectPage(userPage, lambda);

        // 获取分页数据
        long total = userPage.getTotal();
        List<User> users = userPage.getRecords();
        // user   ->  userVO
        List<UserVO> userVOS = users.stream().map(user -> {
            UserVO userVO = new UserVO();
            BeanUtils.copyProperties(user, userVO);

            //  部门名称
            String deptName = deptMapper.selectById(user.getDeptId()).getDeptName();
            userVO.setDeptName(deptName);
            // 角色名称列表
            LambdaQueryWrapper<UserRole> lambda1 = new QueryWrapper<UserRole>().lambda();
            lambda1.eq(UserRole::getUserId, user.getId());
            List<Integer> rids = userRoleMapper.selectList(lambda1).stream()
                    .map(ur -> ur.getRoleId())
                    .collect(Collectors.toList());


            // 设置角色id
            userVO.setRoleId(rids);

            List<String> roleNames = roleMapper.selectByIds(rids).stream()
                    .map(role -> role.getRoleCh())
                    .collect(Collectors.toList());
            userVO.setRoleNames(roleNames);

            return userVO;
        }).collect(Collectors.toList());

        return ResponseResult.success()
                .data("total", total)
                .data("tableData", userVOS);
    }

    @Override
    public ResponseResult addUser(UserForm userForm) {

        //  user  user_role
        User user = new User();
        BeanUtils.copyProperties(userForm, user);

        // 数据库中用户名字段是唯一索引  用户名重复 则抛出异常  设置默认密码
        String defaultPassword = "111111";
        String salt = RandomUtil.randomString(8);
        String hashPwd = new SimpleHash("MD5", defaultPassword, salt, 10).toHex();

        user.setPassword(hashPwd);
        user.setSalt(salt);

        try {
            baseMapper.insert(user);
        }catch (DuplicateKeyException e){
            throw  new BusinessException("用户名已存在");
        }


        Integer uid = user.getId();


        // roleId   userId
        userForm.getRoleId().forEach(rid -> {
            UserRole userRole = new UserRole(uid, rid);
            userRoleMapper.insert(userRole);
        });


        return ResponseResult.success();
    }

    @Override
    public ResponseResult editUser(UserForm userForm) {

        //  user
        User user = new User();
        BeanUtils.copyProperties(userForm,user);
        baseMapper.updateById(user);

        //  user_role   uid  10    [1,2,3]  [2,3]  删除   添加
        LambdaQueryWrapper<UserRole> lambda = new QueryWrapper<UserRole>().lambda();
        lambda.eq(UserRole::getUserId,user.getId());
        userRoleMapper.delete(lambda);

        // 添加
        userForm.getRoleId().forEach(rid->{
            UserRole userRole = new UserRole(user.getId(), rid);
            userRoleMapper.insert(userRole);
        });

        return ResponseResult.success();
    }

    @Override
    public ResponseResult resetPassword(Integer uid) {

        String defaultPassword = "111111";
        String salt = RandomUtil.randomString(8);
        String hashPwd = new SimpleHash("MD5", defaultPassword, salt, 10).toHex();
        User user = new User();
        user.setPassword(hashPwd);
        user.setSalt(salt);
        user.setId(uid);

        baseMapper.updateById(user);

        return ResponseResult.success();
    }

    @Override
    public ResponseResult changeUserState(HashMap<String, Integer> params) {

        User user = new User();
        user.setId(params.get("uid"));
        user.setState(params.get("state"));
        System.out.println("user = " + user);
        baseMapper.updateById(user);
        return ResponseResult.success();
    }

    //"[1,2,3]"
    @Override
    public ResponseResult deleteUsers(String ids) {

        String[] split = ids.split(",");
        List<Integer> uIds = JSONUtil.toList(JSONUtil.toJsonStr(split), Integer.class);

        // 根据用户id  删除用户信息
        baseMapper.deleteByIds(uIds);
        //  删除用户关联的角色信息   user_role
        LambdaQueryWrapper<UserRole> lambda = new QueryWrapper<UserRole>().lambda();
        lambda.in(UserRole::getUserId,uIds);
        userRoleMapper.delete(lambda);

        return ResponseResult.success();
    }

    @Override
    public ResponseResult createUserMenu(HttpServletRequest request) {

        //  获取token
        String authorization = request.getHeader("authentication");
        Integer id = (Integer) jwtUtil.analyzingToken("userInfo", authorization).get("id");

        // 根据id 查询用户角色id  user_role
        LambdaQueryWrapper<UserRole> lambda = new QueryWrapper<UserRole>().lambda();
        lambda.eq(UserRole::getUserId,id);
        List<Integer> rids = userRoleMapper.selectList(lambda)
                .stream().map(ur -> ur.getRoleId())
                .collect(Collectors.toList());


        // 根据角色id  查询权限id     role_permission
        LambdaQueryWrapper<RolePermission> lambda1 = new QueryWrapper<RolePermission>().lambda();
        lambda1.in(RolePermission::getRoleId,rids);

        Set<Integer> pIds = rolePermissionMapper.selectList(lambda1)
                .stream()
                .map(rolePermission -> rolePermission.getPerId())
                .collect(Collectors.toSet());

        //  根据权限id 获取权限信息
        LambdaQueryWrapper<Permission> lambda2 = new QueryWrapper<Permission>().lambda();
        lambda2.in(Permission::getId,pIds)
                .ne(Permission::getIsMenu,2);

        List<Permission> permissions = permissionMapper.selectList(lambda2);

        return ResponseResult.success().data("DBPermissions",permissions);
    }
}




